package org.eclipse.emf.ecore.xcore.util; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.eclipse.emf.codegen.ecore.genmodel.GenClass; import org.eclipse.emf.codegen.ecore.genmodel.GenDataType; import org.eclipse.emf.codegen.ecore.genmodel.GenEnum; import org.eclipse.emf.codegen.ecore.genmodel.GenEnumLiteral; import org.eclipse.emf.codegen.ecore.genmodel.GenFeature; import org.eclipse.emf.codegen.ecore.genmodel.GenModel; import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage; import org.eclipse.emf.codegen.ecore.genmodel.GenOperation; import org.eclipse.emf.codegen.ecore.genmodel.GenPackage; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EEnumLiteral; import org.eclipse.emf.ecore.EGenericType; import org.eclipse.emf.ecore.EModelElement; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.ETypeParameter; import org.eclipse.emf.ecore.ETypedElement; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.EcoreValidator; import org.eclipse.emf.ecore.xcore.XAnnotation; import org.eclipse.emf.ecore.xcore.XAnnotationDirective; import org.eclipse.emf.ecore.xcore.XAttribute; import org.eclipse.emf.ecore.xcore.XClass; import org.eclipse.emf.ecore.xcore.XClassifier; import org.eclipse.emf.ecore.xcore.XDataType; import org.eclipse.emf.ecore.xcore.XEnum; import org.eclipse.emf.ecore.xcore.XEnumLiteral; import org.eclipse.emf.ecore.xcore.XGenericType; import org.eclipse.emf.ecore.xcore.XMember; import org.eclipse.emf.ecore.xcore.XModelElement; import org.eclipse.emf.ecore.xcore.XOperation; import org.eclipse.emf.ecore.xcore.XPackage; import org.eclipse.emf.ecore.xcore.XParameter; import org.eclipse.emf.ecore.xcore.XReference; import org.eclipse.emf.ecore.xcore.XStructuralFeature; import org.eclipse.emf.ecore.xcore.XTypeParameter; import org.eclipse.emf.ecore.xcore.XTypedElement; import org.eclipse.emf.ecore.xcore.XcoreFactory; import org.eclipse.emf.ecore.xcore.XcorePackage; import org.eclipse.emf.ecore.xcore.mappings.XClassMapping; import org.eclipse.emf.ecore.xcore.mappings.XDataTypeMapping; import org.eclipse.emf.ecore.xcore.mappings.XEnumLiteralMapping; import org.eclipse.emf.ecore.xcore.mappings.XFeatureMapping; import org.eclipse.emf.ecore.xcore.mappings.XOperationMapping; import org.eclipse.emf.ecore.xcore.mappings.XPackageMapping; import org.eclipse.emf.ecore.xcore.mappings.XcoreMapper; import org.eclipse.xtext.xbase.XBlockExpression; import com.google.inject.Inject; public class EcoreXcoreBuilder { @Inject private XcoreMapper mapper; @Inject private XcoreJvmInferrer jvmInferrer; List<Runnable> runnables = new ArrayList<Runnable>(); GenModel genModel; public void initialize(GenModel genModel) { this.genModel = genModel; } public XPackage getXPackage(EPackage ePackage) { XPackage xPackage = XcoreFactory.eINSTANCE.createXPackage(); XPackageMapping mapping = mapper.getMapping(xPackage); mapping.setEPackage(ePackage); mapper.getToXcoreMapping(ePackage).setXcoreElement(xPackage); handleAnnotations(ePackage, xPackage); String name = ePackage.getName(); String nsPrefix = ePackage.getNsPrefix(); if (name.equals(nsPrefix)) { nsPrefix = null; } GenPackage genPackage = genModel.findGenPackage(ePackage); mapping.setGenPackage(genPackage); mapper.getToXcoreMapping(genPackage).setXcoreElement(xPackage); String basePackage = genPackage.getBasePackage(); if (basePackage != null && basePackage.length() > 0) { name = basePackage + "." + name; } xPackage.setName(name); String nsURI = ePackage.getNsURI(); if (name.equals(nsURI)) { nsURI = null; } if (nsPrefix != null || nsURI != null) { XAnnotation ecoreAnnotation = null; for (XAnnotation xAnnotation : xPackage.getAnnotations()) { if (EcorePackage.eNS_URI.equals(xAnnotation.getSource())) { ecoreAnnotation = xAnnotation; break; } } if (ecoreAnnotation == null) { ecoreAnnotation = XcoreFactory.eINSTANCE.createXAnnotation(); ecoreAnnotation.setSource(getXAnnotationDirective(xPackage, EcorePackage.eNS_URI)); } if (nsPrefix != null) { ecoreAnnotation.getDetails().put("nsPrefix", nsPrefix); } if (nsURI != null) { ecoreAnnotation.getDetails().put("nsURI", nsURI); } xPackage.getAnnotations().add(ecoreAnnotation); } EAnnotation eAnnotation = ePackage.getEAnnotation(XcorePackage.eNS_URI); if (eAnnotation != null) { for (Map.Entry<String, String> detail : eAnnotation.getDetails()) { XAnnotationDirective xAnnotationDirective = XcoreFactory.eINSTANCE.createXAnnotationDirective(); xAnnotationDirective.setName(detail.getKey()); xAnnotationDirective.setSourceURI(detail.getValue()); xPackage.getAnnotationDirectives().add(xAnnotationDirective); } } for (EClassifier eClassifier : ePackage.getEClassifiers()) { XClassifier xClassifier = getXClassifier(eClassifier); xPackage.getClassifiers().add(xClassifier); } return xPackage; } public void link() { // Hook up local references. // for (Runnable runnable : runnables) { runnable.run(); } runnables.clear(); } void handleAnnotations(final EModelElement eModelElement, final XModelElement xModelElement) { runnables.add (new Runnable() { public void run() { for (EAnnotation eAnnotation : eModelElement.getEAnnotations()) { if (xModelElement instanceof XPackage && GenModelPackage.eNS_URI.equals(eAnnotation.getSource())) { XAnnotation xAnnotation = null; for (Map.Entry<String, String> detail : eAnnotation.getDetails()) { if ("basePackage".equals(detail.getKey())) { // This is already handled from the GenPackage. // XPackage xPackage = (XPackage)xModelElement; // xPackage.setName(detail.getValue() + "." + xPackage.getName()); } else { if (xAnnotation == null) { xAnnotation = XcoreFactory.eINSTANCE.createXAnnotation(); // TODO // map(xAnnotation, eAnnotation); xAnnotation.setSource(getXAnnotationDirective(xModelElement, GenModelPackage.eNS_URI)); } xAnnotation.getDetails().put(detail.getKey(), detail.getValue()); } } if (xAnnotation != null) { xModelElement.getAnnotations().add(xAnnotation); } } else if (xModelElement instanceof XPackage && EcorePackage.eNS_URI.equals(eAnnotation.getSource())) { XAnnotation xAnnotation = null; for (Map.Entry<String, String> detail : eAnnotation.getDetails()) { String key = detail.getKey(); if (!"nsPrefix".equals(key) && !"nsURI".equals(key)) { if (xAnnotation == null) { xAnnotation = XcoreFactory.eINSTANCE.createXAnnotation(); // TODO // map(xAnnotation, eAnnotation); xAnnotation.setSource(getXAnnotationDirective(xModelElement, EcorePackage.eNS_URI)); } xAnnotation.getDetails().put(key, detail.getValue()); } } if (xAnnotation != null) { xModelElement.getAnnotations().add(xAnnotation); } } else if (XcorePackage.eNS_URI.equals(eAnnotation.getSource())) { // Ignore } // Ignore the empty annotations, such as those that store the body. // else if (!EcorePackage.eNS_URI.equals(eAnnotation.getSource()) || !eAnnotation.getDetails().isEmpty()) { XAnnotation xAnnotation = XcoreFactory.eINSTANCE.createXAnnotation(); // TODO // map(xAnnotation, eAnnotation); String source = eAnnotation.getSource(); xAnnotation.setSource(getXAnnotationDirective(xModelElement, source)); for (Map.Entry<String, String> detail : eAnnotation.getDetails()) { xAnnotation.getDetails().put(detail.getKey(), detail.getValue()); } xModelElement.getAnnotations().add(xAnnotation); } } } }); } XAnnotationDirective getXAnnotationDirective(XModelElement xModelElement, String source) { XPackage xPackage = (XPackage)EcoreUtil.getRootContainer(xModelElement); for (XAnnotationDirective xAnnotationDirective : xPackage.getAnnotationDirectives()) { if (source.equals(xAnnotationDirective.getSourceURI())) { return xAnnotationDirective; } } XAnnotationDirective xAnnotationDirective = XcoreFactory.eINSTANCE.createXAnnotationDirective(); xAnnotationDirective.setSourceURI(source); // TODO URI sourceURI = URI.createURI(source); String name = sourceURI.lastSegment(); if (name == null) { name = sourceURI.authority().replaceAll("\\.", "_"); } xAnnotationDirective.setName(name); xPackage.getAnnotationDirectives().add(xAnnotationDirective); return xAnnotationDirective; } XClassifier getXClassifier(final EClassifier eClassifier) { final XClassifier xClassifier = eClassifier instanceof EClass ? getXClass((EClass)eClassifier) : eClassifier instanceof EEnum ? getXEnum((EEnum)eClassifier) : getXDataType((EDataType)eClassifier); handleAnnotations(eClassifier, xClassifier); xClassifier.setName(eClassifier.getName()); String instanceTypeName = eClassifier.getInstanceTypeName(); if (instanceTypeName != null) { final String finalInstanceTypeName = instanceTypeName; runnables.add (new Runnable() { public void run() { Diagnostic diagnostic = EcoreValidator.EGenericTypeBuilder.INSTANCE.parseInstanceTypeName(finalInstanceTypeName); xClassifier.setInstanceType(jvmInferrer.getJvmTypeReference((EGenericType)diagnostic.getData().get(0), eClassifier)); } }); } for (ETypeParameter eTypeParameter : eClassifier.getETypeParameters()) { XTypeParameter xTypeParameter = getXTypeParameter(eTypeParameter); xClassifier.getTypeParameters().add(xTypeParameter); } return xClassifier; } XClass getXClass(EClass eClass) { XClass xClass = XcoreFactory.eINSTANCE.createXClass(); XClassMapping mapping = mapper.getMapping(xClass); mapping.setEClass(eClass); GenClass genClass = (GenClass)genModel.findGenClassifier(eClass); mapping.setGenClass(genClass); mapper.getToXcoreMapping(eClass).setXcoreElement(xClass); mapper.getToXcoreMapping(genClass).setXcoreElement(xClass); if (eClass.isInterface()) { xClass.setInterface(true); } else if (eClass.isAbstract()) { xClass.setAbstract(true); } for (EGenericType eGenericSuperType : eClass.getEGenericSuperTypes()) { xClass.getSuperTypes().add(getXGenericType(eGenericSuperType)); } for (EStructuralFeature eStructuralFeature : eClass.getEStructuralFeatures()) { XStructuralFeature xStructuralFeature; if (eStructuralFeature instanceof EReference) { xStructuralFeature = getXReference((EReference)eStructuralFeature); } else { xStructuralFeature = getXAttribute((EAttribute)eStructuralFeature); } xClass.getMembers().add(xStructuralFeature); } for (EOperation eOperation : eClass.getEOperations()) { XOperation xOperation = getXOperation(eOperation); xClass.getMembers().add(xOperation); } return xClass; } XOperation getXOperation(EOperation eOperation) { XOperation xOperation = XcoreFactory.eINSTANCE.createXOperation(); XOperationMapping mapping = mapper.getMapping(xOperation); mapping.setEOperation(eOperation); GenOperation genOperation = (GenOperation)genModel.findGenOperation(eOperation); mapping.setGenOperation(genOperation); mapper.getToXcoreMapping(eOperation).setXcoreElement(xOperation); mapper.getToXcoreMapping(genOperation).setXcoreElement(xOperation); handleXTypedElement(xOperation, eOperation); for (EParameter eParameter : eOperation.getEParameters()) { XParameter xParameter = getXParameter(eParameter); xOperation.getParameters().add(xParameter); } for (ETypeParameter eTypeParameter : eOperation.getETypeParameters()) { XTypeParameter xTypeParameter = getXTypeParameter(eTypeParameter); xOperation.getTypeParameters().add(xTypeParameter); } for (EGenericType eException : eOperation.getEGenericExceptions()) { XGenericType xException = getXGenericType(eException); xOperation.getExceptions().add(xException); } EAnnotation ecoreAnnotation = eOperation.getEAnnotation(EcorePackage.eNS_URI); if (ecoreAnnotation != null && !ecoreAnnotation.getContents().isEmpty()) { EObject body = ecoreAnnotation.getContents().get(0); if (body instanceof XBlockExpression) { xOperation.setBody((XBlockExpression)body); } } return xOperation; } XParameter getXParameter(EParameter eParameter) { XParameter xParameter = XcoreFactory.eINSTANCE.createXParameter(); //TODO // map(xParameter, eParameter); handleXTypedElement(xParameter, eParameter); return xParameter; } XTypeParameter getXTypeParameter(ETypeParameter eTypeParameter) { XTypeParameter xTypeParameter = XcoreFactory.eINSTANCE.createXTypeParameter(); mapper.getToXcoreMapping(eTypeParameter).setXcoreElement(xTypeParameter); //TODO // map(xTypeParameter, eTypeParameter); xTypeParameter.setName(eTypeParameter.getName()); for (EGenericType eGenericType : eTypeParameter.getEBounds()) { xTypeParameter.getBounds().add(getXGenericType(eGenericType)); } return xTypeParameter; } void handleXTypedElement(XTypedElement xTypedElement, ETypedElement eTypedElement) { handleAnnotations(eTypedElement, xTypedElement); xTypedElement.setName(eTypedElement.getName()); xTypedElement.setType(getXGenericType(eTypedElement.getEGenericType())); if (eTypedElement.isUnique() && !(eTypedElement instanceof EReference) && eTypedElement.isMany()) { xTypedElement.setUnique(true); } if (!eTypedElement.isOrdered()) { xTypedElement.setUnordered(true); } int lowerBound = eTypedElement.getLowerBound(); int upperBound = eTypedElement.getUpperBound(); if (lowerBound == 0) { if (upperBound == EStructuralFeature.UNBOUNDED_MULTIPLICITY) { xTypedElement.setMultiplicity(new int [] {}); } else if (upperBound == 1) { // xTypedElement.setMultiplicity(new int [] {-3}); // This is the default. } else { xTypedElement.setMultiplicity(new int [] {0, upperBound}); } } else if (lowerBound == upperBound) { xTypedElement.setMultiplicity(new int [] {lowerBound}); } else if (lowerBound == 1) { if (upperBound == EStructuralFeature.UNBOUNDED_MULTIPLICITY) { xTypedElement.setMultiplicity(new int [] {-2}); } else { xTypedElement.setMultiplicity(new int [] {1, upperBound}); } } else { xTypedElement.setMultiplicity(new int [] {lowerBound, upperBound}); } } XGenericType getXGenericType(final EGenericType eGenericType) { if (eGenericType == null) { return null; } else { final XGenericType xGenericType = XcoreFactory.eINSTANCE.createXGenericType(); // TODO // map(xGenericType, eGenericType); EGenericType lowerBound = eGenericType.getELowerBound(); if (lowerBound != null) { xGenericType.setLowerBound(getXGenericType(lowerBound)); } EGenericType upperBound = eGenericType.getEUpperBound(); if (upperBound != null) { xGenericType.setUpperBound(getXGenericType(upperBound)); } for (EGenericType typeArgument : eGenericType.getETypeArguments()) { xGenericType.getTypeArguments().add(getXGenericType(typeArgument)); } EClassifier eClassifier = eGenericType.getEClassifier(); if (eClassifier != null) { xGenericType.setType(genModel.findGenClassifier(eClassifier)); } else { ETypeParameter eTypeParameter = eGenericType.getETypeParameter(); if (eTypeParameter != null) { xGenericType.setType(genModel.findGenTypeParameter(eTypeParameter)); } } return xGenericType; } } XClassifier getClassifier(XPackage xPackage, String name) { for (XClassifier xClassifier : xPackage.getClassifiers()) { if (name.equals(xClassifier.getName())) { return xClassifier; } } return null; } XStructuralFeature getStructuralFeature(XClass xClass, String name) { for (XMember xMember : xClass.getMembers()) { if (xMember instanceof XStructuralFeature && name.equals(xMember.getName())) { return (XStructuralFeature)xMember; } } return null; } XReference getXReference(EReference eReference) { final XReference xReference = XcoreFactory.eINSTANCE.createXReference(); XFeatureMapping mapping = mapper.getMapping(xReference); mapping.setEStructuralFeature(eReference); GenFeature genFeature = genModel.findGenFeature(eReference); mapping.setGenFeature(genFeature); mapper.getToXcoreMapping(eReference).setXcoreElement(xReference); mapper.getToXcoreMapping(genFeature).setXcoreElement(xReference); if (eReference.isContainment()) { xReference.setContainment(true); if (eReference.isResolveProxies()) { xReference.setResolveProxies(true); } } else if (eReference.isContainer()) { xReference.setContainer(true); if (eReference.isResolveProxies()) { xReference.setResolveProxies(true); } } else if (!eReference.isResolveProxies()) { xReference.setLocal(true); } EReference opposite = eReference.getEOpposite(); if (opposite != null) { xReference.setOpposite(genModel.findGenFeature(opposite)); } for (EAttribute eKey : eReference.getEKeys()) { xReference.getKeys().add(genModel.findGenFeature(eKey)); } handleXStructuralFeature(xReference, eReference); return xReference; } XAttribute getXAttribute(EAttribute eAttribute) { final XAttribute xAttribute = XcoreFactory.eINSTANCE.createXAttribute(); XFeatureMapping mapping = mapper.getMapping(xAttribute); mapping.setEStructuralFeature(eAttribute); GenFeature genFeature = genModel.findGenFeature(eAttribute); mapping.setGenFeature(genFeature); mapper.getToXcoreMapping(eAttribute).setXcoreElement(xAttribute); mapper.getToXcoreMapping(genFeature).setXcoreElement(xAttribute); if (eAttribute.isID()) { xAttribute.setID(true); } String defaultValueLiteral = eAttribute.getDefaultValueLiteral(); if (defaultValueLiteral != null) { xAttribute.setDefaultValueLiteral(defaultValueLiteral); } handleXStructuralFeature(xAttribute, eAttribute); return xAttribute; } void handleXStructuralFeature(XStructuralFeature xStructuralFeature, EStructuralFeature eStructuralFeature) { if (!eStructuralFeature.isChangeable()) { xStructuralFeature.setReadonly(true); } if (eStructuralFeature.isTransient()) { xStructuralFeature.setTransient(true); } if (eStructuralFeature.isVolatile()) { xStructuralFeature.setVolatile(true); } if (eStructuralFeature.isDerived()) { xStructuralFeature.setDerived(true); } if (eStructuralFeature.isUnsettable()) { xStructuralFeature.setUnsettable(true); } handleXTypedElement(xStructuralFeature, eStructuralFeature); } XDataType getXDataType(EDataType eDataType) { XDataType xDataType = XcoreFactory.eINSTANCE.createXDataType(); XDataTypeMapping mapping = mapper.getMapping(xDataType); mapping.setEDataType(eDataType); GenDataType genDataType = (GenDataType)genModel.findGenClassifier(eDataType); mapping.setGenDataType(genDataType); mapper.getToXcoreMapping(eDataType).setXcoreElement(xDataType); mapper.getToXcoreMapping(genDataType).setXcoreElement(xDataType); return xDataType; } XEnum getXEnum(EEnum eEnum) { XEnum xEnum = XcoreFactory.eINSTANCE.createXEnum(); XDataTypeMapping mapping = mapper.getMapping(xEnum); mapping.setEDataType(eEnum); GenEnum genEnum = (GenEnum)genModel.findGenClassifier(eEnum); mapping.setGenDataType(genEnum); mapper.getToXcoreMapping(eEnum).setXcoreElement(xEnum); mapper.getToXcoreMapping(genEnum).setXcoreElement(xEnum); for (EEnumLiteral eEnumLiteral : eEnum.getELiterals()) { XEnumLiteral xEnumLiteral = getXEnumLiteral(eEnumLiteral); GenEnumLiteral genEnumLiteral = genEnum.getGenEnumLiteral(eEnumLiteral.getLiteral()); mapper.getToXcoreMapping(eEnumLiteral).setXcoreElement(xEnumLiteral); mapper.getToXcoreMapping(genEnumLiteral).setXcoreElement(xEnumLiteral); xEnum.getLiterals().add(xEnumLiteral); } return xEnum; } XEnumLiteral getXEnumLiteral(EEnumLiteral eEnumLiteral) { XEnumLiteral xEnumLiteral = XcoreFactory.eINSTANCE.createXEnumLiteral(); XEnumLiteralMapping mapping = mapper.getMapping(xEnumLiteral); mapping.setEEnumLiteral(eEnumLiteral); handleAnnotations(eEnumLiteral, xEnumLiteral); xEnumLiteral.setName(eEnumLiteral.getName()); if (!eEnumLiteral.getName().equals(eEnumLiteral.getLiteral())) { xEnumLiteral.setLiteral(eEnumLiteral.getLiteral()); } xEnumLiteral.setValue(eEnumLiteral.getValue()); return xEnumLiteral; } }